/*
 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ArkResource } from "./shared/ArkResource"

const RESOURCE_TYPE: Record<string, number> = { // Copied from ets2bundle/compiler/src/pre_define.ts
    color: 10001,
    float: 10002,
    string: 10003,
    plural: 10004,
    boolean: 10005,
    intarray: 10006,
    integer: 10007,
    pattern: 10008,
    strarray: 10009,
    media: 20000,
    rawfile: 30000
};

class ResourceContext {
    private bundleName: string = ""
    private moduleName: string = ""
    private resources: Record<string, number> = {}

    initialize(bundleName: string, moduleName: string, resources: Record<string, number>) {
        this.bundleName = bundleName
        this.moduleName = moduleName
        this.resources = resources
    }

    getResourceDescriptor(name: string, key: string, type: string, params?: any[]): Resource {
        if (!this.bundleName) throw new Error("Uninitialized resources")

        let typeId = RESOURCE_TYPE[type]!
        if (typeId == undefined) throw new Error("Illegal resource type: " + type)

        let id = this.resources[key]
        if (id == undefined) throw new Error("No such resource: " + key)

        return this.getResourceDescriptorFromRaw(name, id, typeId, params)
    }

    getRawfileResourceDescriptor(name: string, key: string): Resource {
        if (!this.bundleName) throw new Error("Uninitialized resources")
        return this.getResourceDescriptorFromRaw(name, 0, RESOURCE_TYPE.rawfile, [key])
    }

    private getResourceDescriptorFromRaw(name: string, id: number, type: number, params?: any[]): Resource {
        return new ArkResource(
            this.bundleName,
            this.moduleName,
            id,
            type,
            name,
            params
        )
    }
}

const resourceContext = new ResourceContext()


// TODO consider resolving resources in plugin

const KEY_SCOPE_SPLIT_REGEXP = new RegExp("(.*?)\\.(.*)")

function getAppKey(key: string): string {
    let parts = key.match(KEY_SCOPE_SPLIT_REGEXP)
    if (!parts) throw new Error("Illegal key: " + key)
    if (parts[1] !== "app") throw new Error("Only 'app' resources are supported") // TODO 'sys' resources
    return parts[2]
}

export function _r(name: string, ...params: any[]): Resource {
    let key = getAppKey(name)
    let type = key.split(".", 1)[0]
    return resourceContext.getResourceDescriptor(name, key, type, params)
}

export function _rawfile(name: string): Resource {
    // TODO Does rawfile support extra params?
    return resourceContext.getRawfileResourceDescriptor(name, getAppKey('app.' + name))
}

// /** @internal */
export function __registerResources(bundleName: string, moduleName: string, resources: Record<string, number>) {
    if (!bundleName) throw new RangeError("Illegal bundle name")
    if (!moduleName) throw new RangeError("Illegal module name")

    resourceContext.initialize(bundleName, moduleName, resources)
}